import { isNumber } from "@tarojs/shared";
import { useDebounce, useUpdateEffect } from "ahooks";
import { useRef, useState } from "react";

type UseCounter = {
  // defaultValue?: number;
  precision?: number;
  value?: number | "";
  min?: number;
  max?: number;
  onChange?: (e?: number) => void;
};

/**
 * 格式化字符串,返回符合数字格式的字符串
 * @param str
 * @returns string
 */
function formatNumberString(str) {
  if (str === "-" || str === ".") return str;

  return str
    .replace(/[^\d.-]/g, "") // 移除非数字、非小数点、非减号的字符
    .replace(
      /^(-)?([^.]*\.?)(.*)$/,
      (_, sign, prefix, rest) =>
        (sign || "") + // 保留开头的减号（如果有）
        prefix + // 保留小数点前的部分和第一个小数点
        rest.replace(/[^\d]/g, "") // 移除剩余部分的所有非数字字符
    )
    .replace(/(?!^)-/g, ""); // 移除非开头的减号
}

// 处理数值
const processInput = (value, precision, min, max): number => {
  if (value === "-" || value === ".") {
    value = 0;
  }

  const [, dec = ""] = value.toString().split(".");
  value =
    dec === ""
      ? value
      : Number(value).toFixed(Math.min(precision ?? 0, dec.length));

  // 处理min/max限制
  if (isNumber(min) && Number(value) < min) {
    return min;
  }
  if (isNumber(max) && Number(value) > max) {
    return max;
  }

  return value;
};

export default (value?: number, options: UseCounter = {}) => {
  const { precision, max, min, onChange } = options;

  // 用于同步value值，避免不必要的重复刷新
  const lastValue = useRef<any>();

  const [input, setInput] = useState<string | number>(value ?? "");
  const debouncedValue = useDebounce(input, { wait: 500 });

  useUpdateEffect(() => {
    if (value !== lastValue.current) {
      setInput(value as string | number);
      lastValue.current = value;
    }
  }, [value]);

  useUpdateEffect(() => {
    if (input !== lastValue.current) {
      let val: undefined | number;

      if (input !== "") {
        val = processInput(debouncedValue, precision, min, max);
        setInput(val);
        val = Number(val);
      }

      if (val !== value) {
        lastValue.current = val;
        onChange?.(val);
      }
    }
  }, [debouncedValue]);

  // 加
  const inc = () => setInput((e) => Number(e) + 1);
  // 减
  const dec = () => setInput((e) => Number(e) - 1);

  const set = (e: number | string = "") => {
    const res = isNumber(e) ? e : formatNumberString(e);
    console.log("res", res);
    setInput(res);
  };

  return [
    input,
    {
      inc,
      dec,
      set,
    },
  ] as const;
};
